home *** CD-ROM | disk | FTP | other *** search
- program VarPar;
-
- { A simple program to demonstrate use of type-safe variable number of
- parameters in Delphi. Written Mars 1995 by Hallvard Vassbotn
- hallvard@falcon.no }
-
- uses WinCrt, SysUtils;
-
- { These are predefined in System:
- const
- vtInteger = 0;
- vtBoolean = 1;
- vtChar = 2;
- vtExtended = 3;
- vtString = 4;
- vtPointer = 5;
- vtPChar = 6;
- vtObject = 7;
- vtClass = 8;
-
- type
- TVarRec = record
- case Integer of
- vtInteger: (VInteger: Longint; VType: Byte);
- vtBoolean: (VBoolean: Boolean);
- vtChar: (VChar: Char);
- vtExtended: (VExtended: PExtended);
- vtString: (VString: PString);
- vtPointer: (VPointer: Pointer);
- vtPChar: (VPChar: PChar);
- vtObject: (VObject: TObject);
- vtClass: (VClass: TClass);
- end;
- }
-
- const
- TypeNames : array [vtInteger..vtClass] of PChar =
- ('Integer', 'Boolean', 'Char', 'Extended', 'String',
- 'Pointer', 'PChar', 'Object', 'Class');
-
- {
- According to the on-line docs (search for TVarRec), array of const
- parameters are treated like array of TVarRec by the compiler.
- This example will work just as well if you change the declaration of
- TestMultiPar to:
-
- procedure TestMultiPar(const Args: array of TVarRec);
-
- This would make the implementation of the routine cleaner (no absolute
- variable declaration), but the interface would be less understandable
- to the user of the routine.
-
- The compiler looks at the parameters and builds the array directly on the
- stack. For each item in the array it also sets the VType field to one
- of the pre-defined constants vtXXXX. The actual value is always sent as
- four bytes of information. For the Boolean and Char types, only the first
- byte contains useful information.
-
- So, go ahead, now you can write all those neat routines with variable
- number of parameters - and still keep the type safety!
- }
-
- function PtrToHex(P: pointer): string;
- begin
- Result := IntToHex(Seg(P^), 4) + ':' + IntToHex(Ofs(P^), 4);
- end;
-
- procedure TestMultiPar(const Args: array of const);
- var
- ArgsTyped : array [0..$fff0 div sizeof(TVarRec)] of TVarRec absolute Args;
- i : integer;
- begin
- for i := Low(Args) to High(Args) do
- with ArgsTyped[i] do
- begin
- Write('Args[', i, '] : ', TypeNames[VType], ' = ');
- case VType of
- vtInteger: writeln(VInteger);
- vtBoolean: writeln(VBoolean);
- vtChar: writeln(VChar);
- vtExtended: writeln(VExtended^:0:4);
- vtString: writeln(VString^);
- vtPointer: writeln(PtrToHex(VPointer));
- vtPChar: writeln(VPChar);
- vtObject: writeln(PtrToHex(Pointer(VObject)));
- vtClass: writeln(PtrToHex(Pointer(VClass)));
- end;
- end;
- end;
-
- var
- MyObj : TObject;
- begin
- Writeln('Test of type-safe variable number of parameters in Delphi:');
- MyObj := TObject.Create;
- TestMultiPar([123, 45.67, PChar('ASCIIZ'), 'Hello, world!', true, 'X',
- @ShortDayNames, TObject, MyObj]);
- MyObj.Free;
-
- { To verify that the type-safety is used in the supplied formatting routines,
- try this: }
- writeln(Format('%d', ['hi']));
- { The supplied parameter is not of the type expected. The '%d' format string
- signals that the parameter should be an integer value, but instead we
- send a string. At run-time this will generate a exception, and if you
- have enabled IDE-trapping of exceptions, Delphi will show you the offending
- line. Using c-type sprintf funtions like this will result in undefined
- behaviour (read: system crash, GP or whatever) }
- end.
-